/*****************************************************************************
 *   Copyright 2005 Tim A Wang
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 ****************************************************************************/
package com.jb.identity.security;

import com.jb.faces.application.FacesMessage;
import com.jb.faces.context.FacesContext;
import com.jb.framework.PersistentContext;
import com.jb.framework.PersistentManagerRegistry;
import com.jb.framework.database.Predicate;
import com.jb.identity.domain.Address;
import com.jb.identity.domain.Friendship;
import com.jb.identity.domain.Group;
import com.jb.identity.domain.GroupMembership;
import com.jb.identity.domain.UserAccount;
import com.jb.security.SecurityManager;
import com.jb.web.application.configuration.CreateSchema;
import com.jb.web.context.WebContext;
import com.jb.web.session.SessionUser;

import java.util.List;

import javax.print.attribute.standard.Severity;


/**
 * Implementation of Security manager that goes to file system for user account
 * information.
 */
public class DBSecurityManager implements SecurityManager {

    public void initialize(FacesContext ctx) {
        CreateSchema cs = new CreateSchema();     
        cs.createTable(Address.class, true);
        cs.createTable(UserAccount.class, true);
        
        UserAccount userAccount = new UserAccount();
        userAccount.setId("root");
        userAccount.setUserName("root");
        userAccount.setPassword("welcome");
        userAccount.setAccess(0);
        userAccount.update(null);
        
        cs.createTable(Friendship.class, true);
        cs.createTable(Group.class, true);
        cs.createTable(GroupMembership.class, true);
    }

    public int authorize(FacesContext ctx, SessionUser guest, Object resource) {
        if (resource == null) {
            return 2;
        }
        
        if(resource instanceof SessionUser)
        {
            SessionUser user =(SessionUser)resource;
        if (user.getId().equals(guest.getId())) {
            return 0;
        }


        }
        return 2; //guest can see anything
    }

    public synchronized SessionUser authenticate(FacesContext pCtx,
        String userName, char[] password) {
        
        List users = PersistentManagerRegistry.find(UserAccount.class, new Predicate("username", userName, "="));

        if (users.size() == 0) {
            pCtx.addMessage(this.getClass().getName(),
                new FacesMessage("User " + userName +
                    " not found. Please try again!"));

            return null;
        }

        UserAccount user = (UserAccount) users.get(0);
        if ((user != null) && (password == null)) //password is not required
         {
            user.setLoggedIn(true);
            user.update((PersistentContext) pCtx);  
            return user;
        }
        String pwd= new String(password);
        if (user != null) {
            if ((user.getPassword() != null) &&
                    user.getPassword().equals(pwd)) {
                user.setLoggedIn(true);
                user.update((PersistentContext) pCtx);
              
                return user;
            } else {
                pCtx.addMessage(this.getClass().getName(),
                    new FacesMessage("Invalide Password. Please try again!"));

                return null;
            }
        } else {
            pCtx.addMessage(this.getClass().getName(),
                new FacesMessage("User " + userName +
                    " not found. Please try again!"));
        }

        return null;
    }

    public void logout(FacesContext pCtx, SessionUser user) {
      if(user instanceof UserAccount)
      {
        UserAccount u = (UserAccount) user;
        u.setLoggedIn(false);
        u.update((PersistentContext) pCtx);
      }
    }

    public void updateUser(FacesContext ctx, SessionUser user) {
        if(ctx instanceof WebContext && user instanceof UserAccount)
        {
            UserAccount userAccount=(UserAccount)user;
            userAccount.update((WebContext)ctx);
        }else
        {
            ctx.addMessage("Error", new FacesMessage("Expecting WebContext and UserAccount as input"));
        }
    }
    public SessionUser createUser(FacesContext ctx, String userName, String password) {
        if(findUser(ctx, userName)==null)
        {
            UserAccount userAccount = new UserAccount();
            userAccount.setId(userName);
            userAccount.setUserName(userName);
            userAccount.setScreenName(userName);
            userAccount.setPassword(password);
            userAccount.update((WebContext)ctx);
            return userAccount;
        }else {
            ((WebContext)ctx).addErrorMessage(this, "failed to create the user as the username has been used");
            return null;
        }
    }

    public SessionUser findUser(FacesContext ctx, String userName) {
        SessionUser user = null;//(SessionUser) users.get(userName);
        if (user == null) {
            user = (SessionUser) PersistentManagerRegistry.findById(UserAccount.class, userName);
        }
        return user;
    }

    public SessionUser createGuestUser() {
        return new com.jb.security.GuestUser();
    }

    public void synch() {
    }

    public String toString() {
        return "DBSecurityManager";
    }
}
